<template>
  <div id="full-screen-container" ref="dom">
    <template v-if="ready">
      <slot />
    </template>
  </div>
</template>

<script>
/* eslint-disable no-console */
import {
  defineComponent,
  ref,
  nextTick,
  toRefs,
  onMounted,
  onUnmounted,
} from 'vue'
import { debounce, observerDomResize } from '@/utils/index'
import { useGlobal } from '@/store/global'

export default defineComponent({
  name: 'FullScreenContainer',
  props: {
    options: {
      type: Object,
      default: () => ({
        width: 1920,
        height: 1080,
      }),
    },
  },
  setup(props) {
    const globalStore = useGlobal()
    const dom = ref()
    const allWidth = ref(0)
    const allHeight = ref(0)
    const width = ref(0)
    const height = ref(0)
    const ready = ref(false)
    const debounceInitWHFun = ref()
    const domObserver = ref()
    const { options } = toRefs(props)
    const autoResizeInit = async () => {
      await initWH()
      getDebounceInitWHFun()
      bindDomResizeCallBack()
      initConfig()
      setAppScale()
      ready.value = true
    }
    // 初始化宽高
    const initWH = (resize = true) => {
      return new Promise((resolve) => {
        nextTick(() => {
          width.value = dom.value ? dom.value.clientWidth : 0
          height.value = dom.value ? dom.value.clientHeight : 0
          if (!dom.value) {
            console.warn('full-screen-container: dom 不能为空!')
          } else if (!width.value || !height.value) {
            console.warn(
              'full-screen-container: 组件宽度或高度为0px， 可能出现渲染错误！',
            )
          }
          if (typeof onResize === 'function' && resize) onResize()
          resolve()
        })
      })
    }
    const initConfig = () => {
      if (dom.value) {
        const { width, height } = window.screen
        if (options.value.width && options.value.height) {
          allWidth.value = options.value.width
          allHeight.value = options.value.height
          dom.value.style.width = `${options.value.width}px`
          dom.value.style.height = `${options.value.height}px`
          return
        }
        allWidth.value = width
        allHeight.value = height
        dom.value.style.width = `${width}px`
        dom.value.style.height = `${height}px`
      }
    }
    const onResize = () => {
      setAppScale()
    }
    const setAppScale = () => {
      if (dom.value) {
        const currentWidth = document.body.clientWidth
        const currentHeight = document.body.clientHeight
        const scale = {
          x: currentWidth / allWidth.value,
          y: currentHeight / allHeight.value,
        }
        dom.value.style.transform = `scale(${scale.x}, ${scale.y})`
        dom.value.style.width = `${scale.x / width}px`
        dom.value.style.height = `${scale.y / height}px`
        globalStore.setScale(scale)
      }
    }
    const getDebounceInitWHFun = () => {
      debounceInitWHFun.value = debounce(100, initWH)
    }
    const bindDomResizeCallBack = () => {
      if (!dom.value) return
      domObserver.value = observerDomResize(dom.value, debounceInitWHFun.value)
      window.addEventListener('resize', debounceInitWHFun.value)
    }
    const unBindDomResizeCallBack = () => {
      if (!domObserver.value) return
      domObserver.value.disconnect()
      domObserver.value.takeRecords()
      domObserver.value = undefined
      window.addEventListener('resize', debounceInitWHFun.value)
    }
    onMounted(() => {
      nextTick(() => {
        autoResizeInit()
      })
    })
    onUnmounted(() => {
      unBindDomResizeCallBack()
    })
    return {
      dom,
      ready,
    }
  },
})
</script>

<style lang="scss">
#full-screen-container {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
  transform-origin: left top;
  z-index: 999;
}
</style>
